#include <stdio.h>
#include <assert.h>

#include "asmtype.h"
#include "lexical.h"
#include "store.h"
#include "grammar3.h"




static  tetra  inst_dbase[] =
   {         0, 
    0xfa000001,  /* SAVE     $g  */
    0xfb200001,  /* UNSAVE   $g : 0,0,$g */
    0xf8000401,  /* POP      */
    0xfc000002,  /* SYNC     */
    0xf9400002,  /* RESUME   */
    0xf000000C,  /* JMP      */
    0x05000010,  /* FIX      */
    0x07000010,  /* FIXU     */
    0x08000010,  /* FLOT     */
    0x17000010,  /* FINT     */
    0x0a000010,  /* FLOTU    */
    0x15000010,  /* FSQRT    */
    0x0c000010,  /* SFLOT    */
    0x0e000010,  /* SFLOTU   */
    0xfe002020,  /* GET      */
    0xe0000040,  /* SETH     */
    0xe3000040,  /* SETL     */
    0xe1000040,  /* SETMH    */
    0xe2000040,  /* SETML    */
    0xe4000040,  /* INCH     */
    0xe7000040,  /* INCL     */
    0xe5000040,  /* INCMH    */
    0xe6000040,  /* INCML    */
    0xe8000040,  /* ORH      */
    0xeb000040,  /* ORL      */
    0xe9000040,  /* ORMH     */
    0xea000040,  /* ORML     */
    0xec000040,  /* ANDH     */
    0xef000040,  /* ANDL     */
    0xed000040,  /* ANDMH    */
    0xee000040,  /* ANDML    */
    0x40000180,  /* BN       */
    0x44000180,  /* BP       */
    0x42000180,  /* BZ       */
    0x4e000180,  /* BEV      */
    0x48000180,  /* BNN      */
    0x4c000180,  /* BNP      */
    0x4a000180,  /* BNZ      */
    0x46000180,  /* BOD      */
    0x50000180,  /* PBN      */
    0x54000180,  /* PBP      */
    0x52000180,  /* PBZ      */
    0x5e000180,  /* PBEV     */
    0x58000180,  /* PBNN     */
    0x5c000180,  /* PBNP     */
    0x5a000180,  /* PBNZ     */
    0x56000180,  /* PBOD     */
    0xf2000180,  /* PUSHJ    */
    0xf4000180,  /* GETA     */
    0xf6860200,  /* PUT      */
    0x18001800,  /* MUL      */
    0x1a001800,  /* MULU     */
    0x1c001800,  /* DIV      */
    0x1e001800,  /* DIVU     */
    0x20001800,  /* ADD      */
    0x22001800,  /* ADDU     */
    0x24001800,  /* SUB      */
    0x26001800,  /* SUBU     */
    0x28001800,  /* 2ADDU    */
    0x2a001800,  /* 4ADDU    */
    0x2c001800,  /* 8ADDU    */
    0x2e001800,  /* 16ADDU   */
    0x30001800,  /* CMP      */
    0x32001800,  /* CMPU     */
    0x34001800,  /* NEG      */
    0x36001800,  /* NEGU     */
    0x38001800,  /* SL       */
    0x3a001800,  /* SLU      */
    0x3c001800,  /* SR       */
    0x3e001800,  /* SRU      */
    0x60001800,  /* CSN      */
    0x64001800,  /* CSP      */
    0x62001800,  /* CSZ      */
    0x68001800,  /* CSNN     */
    0x6c001800,  /* CSNP     */
    0x6a001800,  /* CSNZ     */
    0x66001800,  /* CSOD     */
    0x6e001800,  /* CSEV     */
    0x70001800,  /* ZSN      */
    0x74001800,  /* ZSP      */
    0x72001800,  /* ZSZ      */
    0x7e001800,  /* ZSEV     */
    0x78001800,  /* ZSNN     */
    0x7c001800,  /* ZSNP     */
    0x7a001800,  /* ZSNZ     */
    0x76001800,  /* ZSOD     */
    0x80001800,  /* LDB      */
    0x82001800,  /* LDBU     */
    0x84001800,  /* LDW      */
    0x86001800,  /* LDWU     */
    0x88001800,  /* LDT      */
    0x8a001800,  /* LDTU     */
    0x8c001800,  /* LDO      */
    0x8e001800,  /* LDOU     */
    0x92001800,  /* LDHT     */
    0x90001800,  /* LDSF     */
    0x94001800,  /* CSWAP    */
    0x96001800,  /* LDUNC    */
    0x98001800,  /* LDVTS    */
    0xb6001800,  /* STUNC    */
    0x9e001800,  /* GO       */
    0xc0001800,  /* OR       */
    0xc2001800,  /* ORN      */
    0xc8001800,  /* AND      */
    0xc6001800,  /* XOR      */
    0xc4001800,  /* NOR      */
    0xca001800,  /* ANDN     */
    0xcc001800,  /* NAND     */
    0xce001800,  /* NXOR     */
    0xd0001800,  /* BDIF     */
    0xd2001800,  /* WDIF     */
    0xd4001800,  /* TDIF     */
    0xd6001800,  /* ODIF     */
    0xd8001800,  /* MUX      */
    0xda001800,  /* SADD     */
    0xdc001800,  /* MOR      */
    0xde001800,  /* MXOR     */
    0xa0001800,  /* STB      */
    0xa2001800,  /* STBU     */
    0xa4001800,  /* STW      */
    0xa6001800,  /* STWU     */
    0xa8001800,  /* STT      */
    0xaa001800,  /* STTU     */
    0xac001800,  /* STO      */
    0xae001800,  /* STOU     */
    0xb2001800,  /* STHT     */
    0xb0001800,  /* STSF     */
    0xb8001800,  /* SYNCD    */
    0xbc001800,  /* SYNCID   */
    0xbe001800,  /* PUSHGO   */
    0x01001000,  /* FCMP     */
    0x02001000,  /* FUN      */
    0x03001000,  /* FEQL     */
    0x04001000,  /* FADD     */
    0x06001000,  /* FSUB     */
    0x14001000,  /* FDIV     */
    0x10001000,  /* FMUL     */
    0x11001000,  /* FCMPE    */
    0x13001000,  /* FEQLE    */
    0x12001000,  /* FUNE     */
    0x16001000,  /* FREM     */
    0xb4180000,  /* STCO     */
    0x9c180000,  /* PREGO    */
    0x9a180000,  /* PRELD    */
    0xba180000,  /* PREST    */
    0xfd400000,  /* SWYM     */
    0x00400000,  /* TRAP     */
    0xff400000,  /* TRIP     */


   };

  

/*
 *  save  $x  
 *  unsave  $x   
 *  pop  $x
 */
tetra  gr_ins_x_reg( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
    if( (INS_SAVE != insid) && (INS_UNSAVE != insid) && (INS_POP != insid) )
    {
    
    }

}


/*
 *  sync  xyz
 */
tetra  gr_ins_xyz_int( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
    && (INS_SYNC == insid)

}

/*
 *  jmp  lable
 */
tetra  gr_ins_lable( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
    && (INS_JMP == insid)

}

/*
 * 如果 对于 $x,$z 模式输入中没有 r_m 这个参数域。
 * 
 * 那么在 gr_instruct_machine 中会补上一个 CNT_SYS 作为参数.
 * 以便于跟 标准的 模式统一..
 *
 * 但是没有办法对  $x, z 来统一，有下面函数转到这里..
 *
 * $x, r_m, $z : fint/fixu/fsqrt/fix/sflot/flot/flotu/sflotu(no round mode)
 * $x, r_m, $z :   fint,fixu,fsqrt,fix
 * $x, r_m, int :   sflot,flot,flotu,sflotu
 *
 */
tetra  gr_ins_x_reg_rm_z_reg( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}


/*
 * $x, 0, rs : get
 *
 * get 指令使用这种格式， 把一个特殊寄存器中的内容读取到  $g 中， 
 * 编码实现中， y 域没有使用， 一直为 0 ， x 域是 $g 的编码， z 域是 rS 的编码。
 *
 */
tetra  gr_ins_x_greg_z_sreg( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}


/*
 * $x, int : 
 * ormh,inch,setl,seth,setmh,incmh,andl,andml,andmh,andh,orl,orml,setml,orh,incl,incml
 * 使用这种格式， $g 的编号被放到 x 域中， int 是个无符号的 16 位的整数，放入 yz 域中。
 *
 * flot, flotu, sflot, sflotu 也可以使用这种格式，对应 2.4.16 的无 round_mode 的形式。
 */
tetra  gr_ins_x_reg_yz_int( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}



/*
 * $x, lable : 
 * $x, @+ofs : 
 * bnp,bn,bz,bp,bod,bnn,bnz,geta,bev,pbn,pbz,pbp,pbod,pbnn,pbnz,pbnp,pbev,pushj
 */
tetra  gr_ins_x_reg_lable( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}


/*
 * rs, 0, $z : put
 * rx, 0, z : put
 *
 * 只用 PUT 使用这个形式，可以没有第二个参数。
 * 
 */
tetra  gr_ins_x_sreg_y_int_z_greg( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}



/*
 * x, yz : pop
 *
 * 标准的书面形式，其中 x 表示返回值得个数.
 * x, yz 都必须是无符号整数。
 *
 */
tetra  gr_ins_x_yz_int( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}
 

/*
 * $x, $y, $z : 
 * $x, $y, z : 
 *
 * mul, mulu, div, divu, add, addu, sub, subu, 2addu, 4addu, 
 * 8addu, 16addu, cmp, cmpu, neg, negu, sl, slu, sr, sru, csn, 
 * csz, csp, csod, csnn, csnz, csnp, csev, zsn, zsz, zsp, zsod, 
 * zsnn, zsnz, zsnp, zsev, ldb, ldbu, ldw, ldwu, ldt, ldtu, ldo, 
 * ldou, ldsf, ldht, cswap, ldunc, ldvts, go, stb, stbu, stw, stwu, 
 * stt, sttu, sto, stou, stsf, stht, stunc, syncd, prest, syncid, 
 * pushgo, or, orn, nor, xor, and, andn, nand, nxor, bdif, wdif, 
 * tdif, odif, mux, sadd, mor, mxor
 * 
 * 这些指令使用这种格式, 第三个操作数可能是 $z, 也可以是一个无符号整数 z。
 *
 * fcmp, fun, feql, fadd, fsub,  fmul, fcmpe, fune, feqle, fdiv, frem 
 * 只使用第一种形式。
 *
 *
 */
tetra  gr_ins_x_y_reg_z_reg_int( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{
}


/*
 * x, $y, $z : 
 * x, $y, z : 
 *
 * stco, preld, prest, prego
 */
tetra  gr_ins_x_int_y_reg_z_reg_int( gr_context * pgrctx, tetra insid, lex_token_t * ptoken )
{

    /* 判断 insid 是否是 STCO, preld, prest, prego */


    /* 判断整数是否超过 255 .. */
    
}



/*
 * 过滤掉参数之间的 逗号，返回需要的 token。
 * 输入: 
 *     pgrctx : gr 上下文定义..
 *     pmaxtk : 允许的最多的 token 个数, 同时也用来返回真正的 token 数目.
 *
 * 输出:
 *     ptoken : 用来承载返回的 token..
 *
 * 返回:
 *     0 表示成功，非 0 表示失败..
 *
 */

tetra  gr_common_get_params( gr_context * pgrctx, tetra * pmaxtk, lex_token_t * ptoken )
{
    tetra  i;
    lex_token_t  ttoken;

    /**/
    if( (NULL == pgrctx) || (NULL == pmaxtk) || (NULL == ptoken) )
    {
        /* 参数错误。 */
        return  6;
    }

    /* 这个值 *pmaxtk 必须是有意义的.. */
    if( *pmaxtk <= 0 )
    {
        return 2;
    }

    
    i = 0;
    do
    {
        /* 读出来下一个 token.. */
        le_next_token( pgrctx->lectx, &(ptoken[i]) );
        
        /* 判断: ERROR,   lable, integer, greg, sreg, CONST, ALPHA */
        if( LEX_TK_ERROR == ptoken[i].type )
        {
            return 2;
        }
        else if( (LEX_TK_COMMAND == ptoken[i].type) || (LEX_TK_INSTRUCT == ptoken[i].type) 
            || (LEX_TK_COLON == ptoken[i].type) || (LEX_TK_COMMA == ptoken[i].type) )
        {
            /* 这些东西都不能是 param  */
            return 3;
        }
        else if( LEX_TK_LINED == token[i].type )
        {
            if( i == 0 )
            {
                /* 没有任何参数 */
                break;
            }
            else
            {
                /* 逗号后面就是换行符了 */
                return 3;
            }
        }
        else
        {
             /* OK, 记下这个 token 了.. */
             i += 1;
        }


        /* 读出来下一个 token.. */
        le_next_token( pgrctx->lectx, &ttoken );

        if( LEX_TK_ERROR == ttoken[i].type )
        {
            return 4;
        }
        else if( LEX_TK_LINED == ttoken[i].type )
        {
            break;
        }
        else if( LEX_TK_COMMA == ttoken[i].type )
        {
            /* 这个正是我要等的东西.. nothing to do */
        }
        else
        {
            /* 不是我需要的，报错.. */
            return 5;
        }

        /* 判断是否超过 3 个参数了..还没有碰到 lined ?.. */
        if( i >= *pmaxtk )
        {
            return 6;
        }
        
    } while(1);

    *pmaxtk = i;
    return 0;
    
}


/*
 * 指令 处理函数。
 * 输入: 
 *     pgrctx : gr 上下文定义..
 *     insid: 已经识别出来的 command 的命令码..
 *
 * 输出:
 * 返回:
 *
 */

tetra  gr_instruct_machine( gr_context * pgrctx, tetra insid )
{
    tetra  i, rc = 0;
    lex_token_t  token[3];


    if( NULL == pgrctx )
    {
        /* 参数错误。 */
        return  6;
    }

    /* 判断 insid 范围.. */
    if( (insid < INS_SAVE) || (insid >INS_TRIP) )
    {
        return  2;
    }


    /* 
     * 处理后继的参数: parm,parm,parm  
     * 这个 for 循环的作用仅仅是去掉 逗号 而已。
     */
    i = 3;
    rc = gr_common_get_params( pgrctx, &i, token );
    if( 0 != rc )
    {
        return 3;
    }


    /* 继续分类.. */
    if( (0 == i) || (3 < i) )
    {
        /* 现在还不支持.. */
        return 7;
    }


    /* 
     * save  $x  |  unsave  $x   |  pop  $x
     * sync  xyz  |  jmp  lable
     */
    if( 1 == i )
    {
        if( LEX_TK_GREG == token[0].type )
        {
            rc = gr_ins_x_reg( pgrctx, insid, token );
        }
        else if( LEX_TK_INTEGER == token[0].type )
        {
            rc = gr_ins_xyz_int( pgrctx, insid, token );            
        }
        else if( LEX_TK_LABLE == token[0].type )
        {
            rc = gr_ins_lable( pgrctx, insid, token );
        }
        else
        {
            return 8;
        }

        if( rc != 0 )
        {
            return 9;
        }
        
    }

    /*
     * $x, $z : fint/fixu/fsqrt/fix/sflot/flot/flotu/sflotu(no round mode)
     * $x, rs : get
     * $x, int : ormh,inch,setl,seth,setmh,incmh,andl,andml,andmh,andh,orl,orml,setml,orh,incl,incml
     * $x, lable : 
     * $x, @+ofs : bnp,bn,bz,bp,bod,bnn,bnz,geta,bev,pbn,pbz,pbp,pbod,pbnn,pbnz,pbnp,pbev,pushj
     * rs, $z : put
     * x, yz : pop
     */
    if( 2 == i )
    {
        if( ( LEX_TK_GREG == token[0].type ) && ( LEX_TK_GREG == token[1].type ) )
        {
            token[2] = token[1];
            
            /* 构造一个 INTEGER token，值是 0.. */
            token[1].type = LEX_TK_CONST;
            token[1].info = CNT_SYS;
            token[1].eat = 0;
            token[1].len = 0;

            rc = gr_ins_x_reg_rm_z_reg( pgrctx, insid, token );
        }
        else if( ( LEX_TK_GREG == token[0].type ) && ( LEX_TK_SREG == token[1].type ) )
        {
            token[2] = token[1];
            
            /* 构造一个 INTEGER token，值是 0.. */
            token[1].type = LEX_TK_INTEGER;
            token[1].eat = 0;
            token[1].len = 0;
            token[1].valint = 0;
            
            rc = gr_ins_x_greg_z_sreg( pgrctx, insid, token );
        }
        else if( ( LEX_TK_GREG == token[0].type ) && ( LEX_TK_INTEGER == token[1].type ) )
        {
            rc = gr_ins_x_reg_yz_int( pgrctx, insid, token );
        }
        else if( ( LEX_TK_GREG == token[0].type ) && ( LEX_TK_LABLE == token[1].type ) )
        {
            rc = gr_ins_x_reg_lable( pgrctx, insid, token );
        }
        else if( ( LEX_TK_GREG == token[0].type ) && ( LEX_TK_ALPHA == token[1].type ) )
        {
            rc = gr_ins_x_reg_lable( pgrctx, insid, token );
        }
        else if( ( LEX_TK_SREG == token[0].type ) && ( LEX_TK_GREG == token[1].type ) )
        {
            token[2] = token[1];
            
            /* 构造一个 INTEGER token，值是 0.. */
            token[1].type = LEX_TK_INTEGER;
            token[1].eat = 0;
            token[1].len = 0;
            token[1].valint = 0;

            rc = gr_ins_x_sreg_y_int_z_greg( pgrctx, insid, token );
        }
        else if( ( LEX_TK_INTEGER == token[0].type ) && ( LEX_TK_INTEGER == token[1].type ) )
        {
            rc = gr_ins_x_yz_int( pgrctx, insid, token );
        }
        else
        {
            return 8;
        }

        if( rc != 0 )
        {
            return 9;
        }
    }


    /*
     * $x, 0, rz : GET     
     * $x, 0, 0 : SAVE    
     *
     * rx, 0, $z : PUT     
     * rx, 0, z : PUT     
     *
     *
     * $x,$y,$z : fdiv,fadd,fmul,fcmp,fun,fcmpe,feqle,fsub,frem,feql,fune
     * $x,$y,z : addu,sr,subu,cmp,negu,cmpu,nand,sub,zsod,add,divu,...
     *
     * $x, r_m, $z :   fint,fixu,fsqrt,fix
     * $x, r_m, int :   sflot,flot,flotu,sflotu
     *
     * x, $y, $z : STCO    
     * x, $y, z : STCO    
     *
     * 0, 0, $z : UNSAVE  
     * 0, 0, z : RESUME  
     *
     */
    if( 3 == i )
    {
        /* 最后一个参数只能是 : sreg, greg, int */
        if( ( LEX_TK_SREG != token[2].type ) 
            && (LEX_TK_GREG != token[2].type) && (LEX_TK_INTEGER != token[2].type) )
        {
            return 3;
        }


        if( LEX_TK_SREG == token[2].type )
        {
            /* $x, 0, rz : GET */
            if( (LEX_TK_GREG != token[0].type) || (LEX_TK_INTEGER != token[1].type) )
            {
                return 4;
            }

            rc = gr_ins_x_greg_z_sreg( pgrctx, insid, token );
        }
        else if( (LEX_TK_GREG == token[0].type) && (LEX_TK_INTEGER == token[1].type) )
        {
            /* $x, 0, 0 : SAVE */
            if( LEX_TK_INTEGER != token[2].type )
            {
                return 6;
            }

            if( (0 != token[1].valint) || (0 != token[2].valint) )
            {
                return 7;
            }

            /* 归一到 $x 模式中了.. */
            rc = gr_ins_x_reg( pgrctx, insid, token );
        }
        else if( (LEX_TK_SREG == token[0].type) && (LEX_TK_INTEGER == token[1].type) )
        {
            /* rx, 0, $z : rx, 0, z : PUT */
            rc = gr_ins_x_sreg_y_int_z_greg( pgrctx, insid, token );
        }
        else if( (LEX_TK_GREG == token[0].type) && (LEX_TK_GREG == token[1].type) )
        {
            /* $x,$y,$z : $x,$y,z */
            rc = gr_ins_x_y_reg_z_reg_int( pgrctx, insid, token );
        }
        else if( (LEX_TK_GREG == token[0].type) && (LEX_TK_CONST == token[1].type) )
        {
            /* $x, r_m, $z : $x, r_m, z */
            rc = gr_ins_x_reg_rm_z_reg( pgrctx, insid, token );
        }
        else if( (LEX_TK_INTEGER == token[0].type) && (LEX_TK_GREG == token[1].type) )
        {
            /* x, $y, $z : x, $y, z */
            rc = gr_ins_x_int_y_reg_z_reg_int( pgrctx, insid, token );
        }
        else if( (LEX_TK_INTEGER == token[0].type) && (LEX_TK_INTEGER == token[1].type) )
        {
            /*  0, 0, $z : UNSAVE     0, 0, z : RESUME   */
            /* 以后考虑.. */
            return 9;
        }
        else
        {
            return 8;
        }

        
        if( rc != 0 )
        {
            return 9;
        }
        
    }
    
    
    return 0;
    
}








/*
 * 伪命令 处理函数。
 * 输入: 
 *     pgrctx : gr 上下文定义..
 *     cmdid: 已经识别出来的 command 的命令码..
 *
 * 输出:
 * 返回:
 *
 */

tetra  gr_pseudo_machine( gr_context * pgrctx, tetra cmdid )
{
    tetra  i, rc = 0;
    
    if( pgrctx == NULL )
    {
        /* 参数错误。 */
        return  GR_ERNO(6);
    }

    /* 判断 cmdid 范围.. */
    if( (cmdid < CMD_BYTE) || (cmdid > CMD_STR_GB18030) )
    {
        return  2;
    }

    /* */

    return 0;
}


/*
 * 模块内部函数..
 *
 * 如果其他处理流程中，遇到词法分析错误。
 * 都交由这个函数来处理。
 * 
 * 基本处理思想: 
 *     输出提示信息，然后清除到行末尾.
 *     应该影响后续的处理流程，没有必要产生输出文件了。
 * 
 */
 
tetra  gr_error_process( gr_context * pgrctx, tetra  errno )
{
    lex_token_t  token;
    tetra  rc = 0;


    /* 清除本行的其他后继 token , 提示错误信息。 */
    do
    {   
        /* 读出来下一个 token.. */
        le_next_token( pgrctx->lectx, &(tmp_token[1]) );

        /* 如果这个也是错误 token , 淹没不理??  */
        
        
    } while( token.type != LEX_TK_LINED )


    /* 行号等等处理.. */
    
    return  rc;
    
}






/*
 *  
 *  返回:  0 -  成功。
 *         1 -  文件末尾。
 *
 *  返回值需要仔细考虑， 这里有点乱..
 *
 */
tetra   gr_run_line( tetra grctx )
{
    lex_token_t  tmp_token[2];
    gr_context * pgrctx;
    tetra  rc = 0;

    /* 输入参数判断.. */
    if( grctx == 0 )
    {
        return GR_ERNO(1);
    }
    pgrctx = (gr_context * )grctx;


    /* 取出首个 token. */
    le_next_token( pgrctx->lectx, &(tmp_token[0]) );


    /* 处理 lable 定义.. */
    if( tmp_token[0].type == LEX_TK_LABLE )
    {
        /* 读出来下一个 token. */
        le_next_token( pgrctx->lectx, &(tmp_token[1]) );

        /* 期望这个 token 是 冒号 */
        if( tmp_token[1].type == LEX_TK_COLON )
        {
            rc = gr_pseudo_lable_define( pgrctx, 2, &(tmp_token[0]) );
        }
        else
        {
            rc = GR_ERNO(4);
        }

        if( rc != 0 )
        {
            gr_error_process( grctx, rc );
            return rc;
        }

        /* 再取出下一个 token. */
        le_next_token( pgrctx->lectx, &(tmp_token[0]) );
        
    }


    /* 如果开放 : 一行定义多个 lable ， 这里可以使用 goto 语句实现。 */


    /* 下面判断是否是 command 还是 instruction ，分别进行后续各自的参数分析.. */
    if( tmp_token[0].type == LEX_TK_COMMAND )
    {
        /* 需要根据不同 伪命令 类型， 分别调用不同的函数来处理。 */
        rc = gr_pseudo_machine( pgrctx, &(tmp_token[0]) );
    }
    else if( tmp_token[0].type == LEX_TK_INSTRUCT )
    {
        /* 判断 段的类型，是否可以使用指令.. */
        if( pgrctx->section_type == ST_SEC_TYPE_TEXT )
        {
            /* 指令部分，有自动机来分类参数类型.. */
            rc = gr_instruct_machine( pgrctx, &(tmp_token[0]) );
        }
        else
        {
            /* 错误提示。清除本行。 返回 。 */
            rc = GR_ERNO(27);
        }
    }
    else if( tmp_token[0].type == LEX_TK_LINED )
    {
        /* 到达行末尾，正常返回成功. */
        rc = 0;
    }
    else if( tmp_token[0].type == LEX_TK_FILED )
    {
        /* 到达 文件 末尾，需要返回特殊的返回值，结束本次 gr 处理。 */
        return GR_ERROR_FILEND;
    }
    else
    {
        /* 不允许其他 token 开始。 */
        /* 错误处理.  */
        rc = 2;
    }

    
    if( rc != 0 )
    {
        gr_error_process( grctx, rc );
        return 1;
    }

    /**/
    return GR_ERROR_GOOD;

}


 
/*
 *  输入: in_context , st_context;
 *  输出: gr_context.
 *
 */

tetra   gr_init_context( tetra  inctx, tetra stctx )
{
    tetra   tmpctx;
    gr_context * pgrctx;
    
    /* */
    if( (inctx == 0) || (stctx == STORE_INVALID_ID) )
    {
        return 0;
    }

    /* */
    pgrctx = (gr_context *) malloc( sizeof(gr_context) );
    if( pgrctx == NULL )
    {
        /* error memmory malloc fail.. */
        return 0;
    }

    /* 初始化信息。 */
    pgrctx->inctx = inctx;
    pgrctx->stctx = stctx;

    tmpctx = le_init_context( inctx );
    if( tmpctx == 0 )
    {
        free( pgrctx );
        return 0;
    }

    pgrctx->lectx = tmpctx; 

    /* 关于段的信息.. */
    pgrctx->section_id = 0;
    pgrctx->section_ofs = 0;
    pgrctx->section_type = 0;

    /**/
    pgrctx->lineno = 0;
    pgrctx->columno = 0;
    
    /* 返回.. */
    tmpctx = (tetra)pgrctx;
    return  tmpctx;
}


tetra  gr_fini_context( tetra grctx )
{
    gr_context * pgrctx;
    
    if( grctx == 0 )
    {
        return 1;
    }

    pgrctx = (gr_context * )grctx;
    
    /* 释放 lex..  */
    le_fini_context( pgrctx->lectx );

    free( pgrctx );

    return 0;
}


int  main()
{
    tetra  inctx, stctx;
    tetra  grctx;
    tetra  rc;
    
    inctx = in_init_context( NULL, 0 );
    if( inctx == 0 )
    {
        printf("err: in_init_context.");
        return 0;
    }

    stctx = st_init_context();
    if( stctx == STORE_INVALID_ID )
    {
        printf("err: st_init_context.");
        return 0;
    }

    grctx = gr_init_context( inctx, stctx );
    if( grctx == 0 )
    {
        printf("err: gr_init_context.");
        return 0;
    }
    
    while(1)
    {
        rc = gr_run_line( grctx );

        if( rc == GR_ERROR_FILEND )
        {
            printf( " find file end.. " );
            break;
        }

        if( rc != 0 )
        {
            printf( " find other error %d.. ", rc );
            break;
        }
    }


#if  0
    st_dump_context( stctx );
#endif

    return 0;
}

